home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1992 The Geometry Center; University of Minnesota
- 1300 South Second Street; Minneapolis, MN 55454, USA;
-
- This file is part of geomview/OOGL. geomview/OOGL is free software;
- you can redistribute it and/or modify it only under the terms given in
- the file COPYING, which you should have received along with this file.
- This and other related software may be obtained via anonymous ftp from
- geom.umn.edu; email: software@geom.umn.edu. */
-
- /* Authors: Charlie Gunn, Stuart Levy, Tamara Munzner, Mark Phillips,
- * Celeste Fowler */
-
- #include "geomclass.h"
- #include "pickP.h"
-
- #define PICK_POSSIBLE(pick, ap) \
- (ap == NULL ? PW_VERT | PW_EDGE | PW_FACE : \
- ((((pick->want & PW_VERT) && \
- (ap->flag & (APF_FACEDRAW | APF_EDGEDRAW | APF_VECTDRAW))) \
- ? PW_VERT : 0) | \
- (((pick->want & PW_EDGE) && \
- (ap->flag & (APF_FACEDRAW | APF_EDGEDRAW | APF_VECTDRAW))) \
- ? PW_EDGE : 0) | \
- (((pick->want & PW_FACE) && \
- (ap->flag & APF_FACEDRAW)) ? PW_FACE : 0)))
-
- int PickFace(int n_verts, Point3 *verts, Pick *pick, Appearance *ap)
- {
- Point3 got, ep;
- int v, e;
-
- if (PolyNearPosZInt(n_verts, verts, pick->thresh, &got, &v, &e, &ep) &&
- got.z < pick->got.z && got.z >= -1)
- return PickFillIn(pick, n_verts, &got, v, e, ap);
- else return 0;
-
- }
-
- int PickFillIn(Pick *pick, int n_verts, Point3 *got, int vertex,
- int edge, Appearance *ap)
- {
- int i, found = 0;
-
- pick->got = *got;
-
- vvcopy(&pick->gcur, &pick->gpath);
-
- found = 0;
- if ((PICK_POSSIBLE(pick, ap) & PW_VERT) && vertex != -1) {
- found |= PW_VERT;
- pick->vi = vertex;
- }
- if ((PICK_POSSIBLE(pick, ap) & PW_EDGE) && edge != -1 ) {
- found |= PW_EDGE;
- pick->ei[0] = edge;
- pick->ei[1] = (edge + 1) % n_verts;
- }
- if (PICK_POSSIBLE(pick, ap) & PW_FACE) {
- found |= PW_FACE;
- pick->fn = n_verts;
- }
- if (found) {
- pick->found = found;
- if (pick->f != NULL) OOGLFree(pick->f);
- pick->f = NULL;
- }
-
- return found;
- }
-
- Geom *
- GeomMousePick(Geom *g, Pick *p, Appearance *ap,
- Transform Tg, double x, double y)
- {
- Pick *pick;
- Transform Txy, T;
-
- pick = p ? p : PickSet(NULL, PA_END);
- TmTranslate(Txy, -x, -y, 0.);
- TmConcat(Tg, Txy, T);
- g = GeomPick(g, pick, ap, T);
- if (g && p) {
- TmInvert(p->Tprim, p->Tmirp);
- TmInvert(T, p->Tw);
- }
- if(p == NULL)
- PickDelete(pick);
- return g;
- }
-
- /*
- * Simple generic Pick routine based on bounding-box intersection.
- * We succeed if the picked point lies within the screen projection of the
- * object, i.e. if the picked point lies within the smallest screen square
- * surrounding the object. The depth is that of the midpoint of the
- * bounding box: average of min and max depth.
- */
- static Geom *
- GenericPick(Geom *g, Pick *p, Appearance *ap, Transform T)
- {
- Geom *bbox;
- HPoint3 min, max;
-
- bbox = GeomBound(g, T);
- BBoxMinMax(bbox, &min, &max);
- if(min.x <= 0 && max.x >= 0 && min.y <= 0 && max.y >= 0 &&
- .5*(min.z + max.z) <= p->got.z) {
- p->got.x = p->got.y = 0;
- p->got.z = .5 * (min.z + max.z);
- p->gprim = g;
- TmCopy(T, p->Tprim);
- return g;
- }
- return NULL;
- }
-
- Geom *
- GeomPick(Geom *g, Pick *p, Appearance *ap, Transform T)
- {
- if(g == NULL)
- return;
-
- if(g->Class->pick == NULL) {
- /* OOGLError(1, "Note: using GenericPick for class %s",
- (*g->Class->name)()); */
- g->Class->pick = (GeomPickFunc *)GenericPick;
- }
- return (*g->Class->pick)(g, p, ap, T);
- }
-
- void
- PickDelete(Pick *p)
- { /* Note we don't GeomDelete(p->gprim); it wasn't RefIncr'd */
- if(p) {
- if (p->f) OOGLFree(p->f); /* free the face list, if any */
- vvfree(&p->gcur);
- vvfree(&p->gpath);
- OOGLFree(p);
- }
- }
-
- Pick *
- PickSet(register Pick *p, int attr, ...)
- {
- va_list al;
- int a;
-
- if(p == NULL) {
- /*
- * Create new Pick structure
- */
- p = OOGLNewE(Pick, "new Pick");
- p->got.x = 0; p->got.y = 0; p->got.z = 1;
- p->thresh = 0.02;
- p->want = 0;
- p->found = 0;
- VVINIT(p->gcur, int, 1);
- VVINIT(p->gpath, int, 1);
- p->gprim = NULL;
- HPt3From(&p->v, 0.0, 0.0, 0.0, 1.0);
- p->vi = -1;
- HPt3From(&p->e[0], 0.0, 0.0, 0.0, 1.0);
- HPt3From(&p->e[1], 0.0, 0.0, 0.0, 1.0);
- p->ei[0] = -1;
- p->ei[1] = -1;
- p->f = NULL;
- p->fn = 0;
- p->fi = -1;
- }
- va_start(al, attr);
- for(a = attr; a != PA_END; a = va_arg(al, int)) {
- switch(a) {
- case PA_WANT: p->want = va_arg(al, int); break;
- case PA_THRESH: p->thresh = va_arg(al, double); break;
- case PA_POINT: p->got = *va_arg(al, Point3 *); break;
- case PA_DEPTH: p->got.z = va_arg(al, double); break;
- case PA_GPRIM: p->gprim = va_arg(al, Geom *); break;
- case PA_TPRIM: TmCopy(*va_arg(al, Transform *), p->Tprim); break;
- case PA_VERT: p->v = *va_arg(al, HPoint3 *); break;
- case PA_EDGE: { HPoint3 *e = va_arg(al, HPoint3 *);
- p->e[0] = e[0];
- p->e[1] = e[1];
- }
- break;
- case PA_FACE: p->f = va_arg(al, HPoint3 *); break;
- case PA_FACEN: p->fn = va_arg(al, int); break;
- default:
- OOGLError(1, "PickSet: unknown attribute %d", a);
- va_end(al);
- return p;
- }
- }
- va_end(al);
- return p;
- }
-
- int
- PickGet(register Pick *p, int attr, void *attrp)
- {
- if(p == NULL)
- return -1;
- switch(attr) {
- case PA_WANT: *(int *)attrp = p->want; return 1;
- case PA_THRESH: *(float *)attrp = p->thresh; return 1;
- case PA_POINT: *(Point3 *)attrp = p->got; break;
- case PA_DEPTH: *(float *)attrp = p->got.z; break;
- case PA_GPRIM: *(Geom **)attrp = p->gprim; break;
- case PA_TPRIM: TmCopy(p->Tprim, *(Transform *)attrp); break;
- case PA_VERT: *(HPoint3 *)attrp = p->v; break;
- case PA_EDGE:
- ((HPoint3 *)attrp)[0] = p->e[0];
- ((HPoint3 *)attrp)[1] = p->e[1];
- break;
- case PA_FACE: *(HPoint3 **)attrp = p->f; break;
- case PA_FACEN: *(int *)attrp = p->fn; break;
- default:
- return -1;
- }
- return p->found;
- }
-